package org.he.auth.service.impl;

import org.he.auth.domain.Permission;
import org.he.auth.service.IPermissionScanService;
import org.he.auth.service.IPermissionService;
import org.he.basic.annotation.HePermission;
import org.he.basic.enums.RequestTypeEnum;
import org.he.basic.util.ClassUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @author He
 * @date 2023/12/2  14:06
 */
@Service
public class PermissionScanServiceImpl implements IPermissionScanService {
    @Value("${permission.scan-package}")
    private String packagenames;
    @Autowired
    private IPermissionService permissionService;

    @Override
    @Transactional
    public void scan() {
        // 1.获取所有的Controller
        List<Class> allClassName = ClassUtils.getAllClassName(packagenames);
//        allClassName.forEach(System.out::println);
        // 2.循环 判断Controller是否有权限注解
        permissionService.deleteAll();
        for (Class clazz : allClassName) {
            HePermission annotation = (HePermission)clazz.getAnnotation(HePermission.class);
            // 如果没有注解 不管
            if (Objects.isNull(annotation)) {
                continue;
            }
            // url 类上url+方法上的url
            RequestMapping annotation2 = (RequestMapping) clazz.getAnnotation(RequestMapping.class);
            String[] value = annotation2.value(); // 类上的url
            // 封装父权限
            Permission parent = new Permission();
            parent.setName(annotation.name());
            parent.setDescs(annotation.desc());
            parent.setSn(clazz.getSimpleName());
            parent.setUrl(annotation2.value()[0]);
            permissionService.insert(parent);
            // 如果有注解 说明 里面的接口是需要权限的
            // 通过反射获取 该Controller中的方法
            Method[] methods = clazz.getMethods();
            // 遍历获取的方法 判断是否有 权限注解
            for (Method method : methods) {
                // 如果有 权限注解
                // 获取注解上的信息 并且封装permission对象
                HePermission annotation1 = method.getAnnotation(HePermission.class);
                if (Objects.isNull(annotation1)) {
                    continue;
                }
                String name = annotation1.name();
                String desc = annotation1.desc();
//                System.out.println(name);
//                System.out.println(desc);
                Permission permission = new Permission();
                permission.setName(name);
                permission.setDescs(desc);

                String simpleName = clazz.getSimpleName();
                String name1 = method.getName();
                permission.setSn(simpleName + ":" + name1); // controller+方法名


//
                // 太麻烦
//                PutMapping annotation3 =  method.getAnnotation(PutMapping.class);
//                if (Objects.nonNull(annotation3)) {
//                    String[] value1 = annotation3.value();
//                    System.out.println(Arrays.toString(value1));
//                }
//                GetMapping annotation4 = method.getAnnotation(GetMapping.class);
//                if (Objects.nonNull(annotation4)) {
//                    String[] value2 = annotation4.value();
//                    System.out.println(Arrays.toString(value2));
//                }
                // 方法上的url
                String methodUrl = getMethodUrl(method);
                permission.setUrl(value[0]+methodUrl);
                permission.setParent(parent);
                // 入库
                permissionService.insert(permission);
            }
        }
    }
    public String getMethodUrl(Method method){
        String methodUrl = "";
        // 取枚举中定义的所有的请求类型
        RequestTypeEnum[] requestTypeEnums = RequestTypeEnum.values();
        for (RequestTypeEnum typeEnum : requestTypeEnums) {
            // 根据枚举中的不同的请求类型的class获取该类型对应的注解对象
            Annotation annotation = method.getAnnotation(typeEnum.getRequestType());
            // 如果该请求类型注解不存在就跳过
            if(Objects.isNull(annotation)){
                continue;
            }
            try {
                // 如果该请求类型注解存在,就获取它里面的value方法
                Class<? extends Annotation> aClass = annotation.annotationType();
                Method annotationMethod = aClass.getMethod("value");
                // 通过invoke调用该对象的value方法,获取结果
                // 反射执行 方法 方法名.invoke(对象)
                String[] value = (String[]) annotationMethod.invoke(annotation);
                // 如果value不为空且长度大于0,就赋值给methodUrl,并跳出循环
                if(value != null && value.length > 0){
                    methodUrl = value[0];
                    break;
                }
            }catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }
        return methodUrl;
    }
}
